package com.andong.service.impl;

import com.andong.domain.entity.SubjectFour;
import com.andong.domain.entity.SubjectProgress;
import com.andong.domain.pojo.PageResult;
import com.andong.domain.pojo.Result;
import com.andong.mapper.SubjectFourMapper;
import com.andong.service.SubjectFourService;
import com.andong.utils.AliOSSUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.andong.utils.SystemConstant.*;

/**
 * @author 王海云
 * @description 针对表【subject_one(科目一题库表)】的数据库操作Service实现
 * @createDate 2024-01-06 20:44:48
 */
@Service
@Slf4j
public class SubjectFourServiceImpl extends ServiceImpl<SubjectFourMapper, SubjectFour>
        implements SubjectFourService {
    @Resource
    SubjectFourMapper subjectFourMapper;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private AliOSSUtils aliOSSUtils;

    @Override
    @Transactional
    public Result addBatch(MultipartFile file) throws IOException {
        // 判断文件类型
        String originalFilename = file.getOriginalFilename();
        assert originalFilename != null;
        if (!originalFilename.endsWith(XLS) && !originalFilename.endsWith(XLSX)) {
            return Result.error(FILE_TYPE_ERROR);
        }
        Long start = System.currentTimeMillis();
        // 读取Excel文件
        InputStream inputStream = file.getInputStream();
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(ZERO);
        Row row;
        // 遍历行和列，读取数据
        List<SubjectFour> list = new ArrayList<>(2000);
        for (int i = 1; i <= sheet.getLastRowNum(); i++) {
            row = sheet.getRow(i);
            SubjectFour subjectFour = SubjectFour.builder()
                    .content(String.valueOf(row.getCell(0)))
                    .optionA(String.valueOf(row.getCell(1)))
                    .optionB(String.valueOf(row.getCell(2)))
                    .optionC(Objects.isNull(row.getCell(3)) ? null : String.valueOf(row.getCell(3)))
                    .optionD(Objects.isNull(row.getCell(4)) ? null : String.valueOf(row.getCell(4)))
                    .answer(String.valueOf(row.getCell(5)))
                    .explanation(String.valueOf(row.getCell(6)))
                    .image(Objects.isNull(row.getCell(7)) ? null : String.valueOf(row.getCell(7)))
                    .build();
            list.add(subjectFour);
            if (i % 2000 == 0) {
                saveBatch(list); // 批量存储提高效率
                // 清空集合
                list.clear();
            }
        }
        // 将最后不满2000的数据插入
        if (!list.isEmpty()) {
            saveBatch(list);
        }
        // 关闭输入流和工作簿对象
        inputStream.close();
        workbook.close();
        Long end = System.currentTimeMillis();
        log.info("解析并上传到数据库用时:{}s", (end - start) * 1.0 / 1000);
        return Result.success();
    }

    @Override
    public Result selectById(Long id) {
        // 1.查询redis缓存中是否存在
        SubjectFour subjectFour = (SubjectFour) redisTemplate.opsForValue().get(SUBJECT_FOUR_CACHE + id);
        if (Objects.nonNull(subjectFour)) {
            return Result.success(subjectFour); // 存在直接返回
        }
        subjectFour = getById(id);
        if (Objects.isNull(subjectFour)) {
            return Result.error(SUBJECT_NOT_EXIST);
        }
        // 存到redis缓存中
        redisTemplate.opsForValue().set(SUBJECT_FOUR_CACHE + id, subjectFour, SUBJECT_CACHE_EXPIRE, TimeUnit.MINUTES);
        return Result.success(subjectFour);
    }

    @Override
    public Result getIds(Boolean isTest) {
        List<SubjectFour> list;
        if (isTest) {
            // 获取50道题目 其中40到单选题 10到多选题
            list = subjectFourMapper.getForty();
            List<SubjectFour> list2 = subjectFourMapper.getTen();
            list.addAll(list2);
        } else {
            list = list();
        }
        List<Long> ids = list.stream().map(SubjectFour::getId).toList();
        return Result.success(ids);
    }

    @Override
    public PageResult queryList(Integer page, Integer pageSize, String name) {
        Page<SubjectFour> subjectFourPage = new Page<>(page, pageSize);
        // 构造Coach条件查询器, 得到Coach分页查询基本信息结果
        subjectFourPage = lambdaQuery()
                .like(name != null, SubjectFour::getContent, name)
                .page(subjectFourPage);

        return new PageResult(subjectFourPage.getTotal(), subjectFourPage.getRecords());
    }

    @Override
    public Result deleteByIds(List<Long> ids) {
        // 删除做题进度包含这些题目的数据
        Db.lambdaUpdate(SubjectProgress.class)
                .in(SubjectProgress::getSubjectId, ids)
                .eq(SubjectProgress::getType, SUBJECT_FOUR_NUMBER)
                .remove();
        // 删除图片
        List<SubjectFour> list = lambdaQuery()
                .in(SubjectFour::getId, ids)
                .list();
        list.forEach(subjectFour -> {
            if (Objects.nonNull(subjectFour.getImage())) {
                aliOSSUtils.delete(subjectFour.getImage());
            }
        });
        // 删除题目
        removeByIds(ids);
        // 清空缓存
        ids.forEach(id -> redisTemplate.delete(SUBJECT_FOUR_CACHE + id));
        return Result.success();
    }

    @Override
    public Result saveOrModify(SubjectFour subjectFour) {
        // 选项列表
        List<String> options = Arrays.asList(subjectFour.getOptionA() == null ? null : "1", subjectFour.getOptionB() == null ? null : "2", subjectFour.getOptionC() == null ? null : "3", subjectFour.getOptionD() == null ? null : "4");
        // 把null的值去掉
        options = options.stream().filter(Objects::nonNull).toList();

        if (!options.contains("1")
                || !options.contains("2")
                || options.size() == 3
                || Objects.isNull(subjectFour.getAnswer())
                || Objects.isNull(subjectFour.getExplanation())
                || (options.size() == 2 && subjectFour.getAnswer().length() != 1)) {
            return Result.error(SUBJECT_ERROR);
        }
        if (Objects.nonNull(subjectFour.getId())) {
            updateById(subjectFour);
            // 更新缓存
            redisTemplate.delete(SUBJECT_FOUR_CACHE + subjectFour.getId());
            return Result.success();
        }
        save(subjectFour);
        return Result.success();
    }

    @Override
    public Result deleteAll() {
        // 删除做题进度
        Db.lambdaUpdate(SubjectProgress.class)
                .eq(SubjectProgress::getType, SUBJECT_FOUR_NUMBER)
                .remove();
        // 删除全部题目
        lambdaUpdate().remove();
        return Result.success();
    }
}




